package com.itheima.reggie.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.entity.Page;
import com.itheima.reggie.entity.dto.DishDto;
import com.itheima.reggie.exception.CustomerException;
import com.itheima.reggie.mapper.CategoryMapper;
import com.itheima.reggie.mapper.DishFlavorMaper;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.DishService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class DishServiceImpl implements DishService {

    @Autowired(required = false)
    private DishMapper dishMapper;

    @Autowired(required = false)
    private DishFlavorMaper dishFlavorMaper;

    @Autowired(required = false)
    private CategoryMapper categoryMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void save(DishDto dishDto) {
        //1.补全信息
        dishDto.setCreateTime(LocalDateTime.now());
        dishDto.setUpdateTime(LocalDateTime.now());
        dishDto.setSort(0); //排序其实页面没有该字段，默认是0
        dishDto.setStatus(1);  //正常售卖

        //2.添加菜品
        dishMapper.save(dishDto);

        //3.取出口味的信息，并且给每一个口味对象补全信息
        List<DishFlavor> flavors = dishDto.getFlavors();
        flavors = flavors.stream().map(dishFlavor -> {
          dishFlavor.setDishId(dishDto.getId());  //补全口味所属的菜品id
          dishFlavor.setCreateTime(LocalDateTime.now());
          dishFlavor.setUpdateTime(LocalDateTime.now());
          dishFlavor.setCreateUser(dishDto.getCreateUser());
          dishFlavor.setUpdateUser(dishDto.getUpdateUser());
          return dishFlavor;
        }).collect(Collectors.toList());

        //4.再把口味信息插入到数据库中
        dishFlavorMaper.batchSave(flavors);//批量导入

        //5. 由于菜品的数据已经发生变化了，那么需要清空缓存
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);
    }

    @Override
    public R<Page<DishDto>> findBypage(Integer page, Integer pageSize, String name) {
        //1.设置当前页和页面大小
        PageHelper.startPage(page,pageSize);

        //2.根据名字查询菜品的列表
        List<Dish> dishList = dishMapper.findByName(name);

        //3.封装pageInfo ，PageInfo<DishDto>
        PageInfo<Dish> pageInfo = new PageInfo<>(dishList);

          //把Dish转换为DishDTO
        List<DishDto> dishDtoList = pageInfo.getList().stream().map(dish -> {
            DishDto dishDto = new DishDto();
            //属性拷贝，属性拷贝的前提：属性名与属性的类型要完全一致
            BeanUtils.copyProperties(dish,dishDto);
            //根据类别的id查找类别
            Category category = categoryMapper.findById(dishDto.getCategoryId());
            dishDto.setCategoryName(category.getName());
            return dishDto;
        }).collect(Collectors.toList());

        //4.把PageInfo转换为Page对象返回.
        Page<DishDto> pageResult = new Page<>(dishDtoList,pageInfo.getTotal(),page,pageSize);
        return R.success(pageResult);
    }

    @Override
    public R<DishDto> findById(Long dishId) {
        //1. 根据id查找到的Dish
        Dish dish = dishMapper.findById(dishId);
        //2.把Dish转换为DishDTo，并且要往Dto设置口味信息
        DishDto dishDto = new DishDto();
        BeanUtils.copyProperties(dish,dishDto);
        //根据菜品的id查找该菜品的口味信息
        List<DishFlavor> dishFlavorList =  dishFlavorMaper.findByDishId(dishId);
        dishDto.setFlavors(dishFlavorList);

        return R.success(dishDto);
    }

    @Override
    @Transactional
    public void updateWithFlavor(DishDto dishDto) {
        //1. 补全修改时间
        dishDto.setUpdateTime(LocalDateTime.now());
        //2 修改菜品
        dishMapper.updateById(dishDto);

        //3. 删除该菜品的所有口味信息
        dishFlavorMaper.deleteByDishId(dishDto.getId());

        //4. 补全口味信息，然后重新插入
        List<DishFlavor> flavors = dishDto.getFlavors();
        List<DishFlavor> dishFlavorList = flavors.stream().map((flavor -> {
            //对每一个元素进行加工
            flavor.setDishId(dishDto.getId());
            flavor.setCreateTime(LocalDateTime.now());
            flavor.setUpdateTime(LocalDateTime.now());
            flavor.setCreateUser(dishDto.getCreateUser());
            flavor.setUpdateUser(dishDto.getUpdateUser());
            return flavor;
        })).collect(Collectors.toList());

        //4. 批量保存口味信息
        dishFlavorMaper.batchSave(dishFlavorList);

        //5. 由于菜品的数据已经发生变化了，那么需要清空缓存
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);
    }

    @Override
    public List<DishDto> findByCategoryId(Long categoryId , Integer status) {
        //优化的思路：根据类别id与状态查找菜品的时候先查询redis，如果redis中没有才真正去查询数据库
        String key = "dish_"+categoryId+"_"+status;
        List<DishDto> dishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);

        //如果Redis中没有要查找数据，那么久应该查找数据库
        if(dishDtoList==null) {
            List<Dish> dishList = dishMapper.fingByCategoryId(categoryId, status);
            //遍历dishList，查看口味信息,把dish转换为dto
            dishDtoList = dishList.stream().map(dish -> {
                DishDto dishDto = new DishDto();
                //属性拷贝
                BeanUtils.copyProperties(dish, dishDto);
                //查看菜品口味信息
                List<DishFlavor> dishFlavorList = dishFlavorMaper.findByDishId(dish.getId());
                dishDto.setFlavors(dishFlavorList);
                //查看该菜品的类别信息
                Category category = categoryMapper.findById(dish.getCategoryId());
                dishDto.setCategoryName(category.getName());
                return dishDto;
            }).collect(Collectors.toList());
            //如果是查询了数据库的数据就应该换缓存在redis中
            redisTemplate.opsForValue().set(key,dishDtoList);
        }
        return dishDtoList;
    }

    //根据id删除菜品
    @Override
    public void deleteById(List<Long> ids) {
        //1.删除之前判断菜品是否在售
        long count = dishMapper.findDishByStatus(ids);
        if (count>0){
            throw new CustomerException("不允许删除在售的菜品");
        }

        //2.如果套餐不是在售状态则删除套餐
        dishMapper.deleteByIds(ids);

        //3.删除关联的口味
        dishFlavorMaper.deleteByFlavorIds(ids);

        //4.

    }


    @Override
    public void updateStatusById(List<Long> ids , Integer status) {
        //2.判断当前菜品的状态，并修改
        dishMapper.updateStatusById(ids,status);
    }
}
